package org.robot.scm.platform.schedule;

import static org.robot.scm.platform.server.LockKey.LOCK_KEY;

import cn.hutool.core.io.FileUtil;
import com.google.common.collect.Lists;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.infra.RedisCacheHelper;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.platform.monitor.Clean3NoticeMonitor;
import org.robot.scm.platform.server.ScmHttpServer;
import org.robot.scm.platform.server.common.DefaultRunner;
import org.robot.scm.pojos.config.BaseConfig;
import org.robot.scm.pojos.config.base.BaseSchedule;
import org.robot.scm.pojos.enums.PlatformEnum;
import org.robot.scm.pojos.platform.server.ExecuteParam;
import org.robot.scm.utils.JsonHelper;
import org.robot.scm.utils.RandomUtil;
import org.slf4j.Logger;

/**
 * @Author : Awn create on 2025/5/19 16:26
 */
public interface CommonCleanJob {

    /**
     * 从模板中按照当前天来截取分批上传文件
     */
    default String upload(BaseSchedule config, Logger log) {
        String sqlSource = ScmHttpServer.getTargetConfig(PlatformEnum.CLEAN3).getCurrentPlatform().getNoticeSrc();

        // 对sourceLines进行裂变
        List<String> sourceLines = fissileLines(FileUtil.readLines(new File(sqlSource), StandardCharsets.UTF_8));

        // 根据dayOfMonth，来分批处理sourceLines
        int currentDay = LocalDate.now().getDayOfMonth();
        if (currentDay > config.getJobBatches()) {
            return null;
        }
        int totalLines = sourceLines.size();
        int linesPerDay = totalLines / config.getJobBatches();
        int startIndex = (currentDay - 1) * linesPerDay;
        int endIndex = currentDay == config.getJobBatches() ? totalLines : startIndex + linesPerDay;

        // 如果endIndex大于totalLines，则结束
        if (endIndex > totalLines) {
            return null;
        }
        List<String> linesToProcess = sourceLines.subList(startIndex, endIndex);
        if (CollectionUtils.isEmpty(linesToProcess)) {
            return null;
        }
        log.info("clean-[{}] range: {} ~ {}, size: {}", currentDay, startIndex, endIndex, linesToProcess.size());

        String fileKey = RandomUtil.uuidNoLine();

        // 替换sql中的占位符${cleanDate}为 2024-01-01 00:00:00 且记录行信息
        File targetFile = new File("assets/telegram/" + fileKey + ".sql");
        if (!targetFile.exists()) {
            targetFile.getParentFile().mkdirs();
        }

        try (OutputStream out = Files.newOutputStream(targetFile.toPath())) {
            for (String fissileLine : linesToProcess) {
                out.write(fissileLine.concat("\n").getBytes(StandardCharsets.UTF_8));
                out.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return fileKey;
    }

    static List<String> fissileLines(List<String> sourceLines) {
        // 保留1个月 天分区 p32,p33,p34,p35,p36,p37,p38,p39,p40,p41,p42,p43,p44,p45,p46,p47,p48,p49,p50,p51,p52,p53,p54,p55,p56,p57,p58,p59
        String clear1MonthDayPartition = Clean3NoticeMonitor.clearPartitionDay(2);
        // 保留1个月 月分区 p2
        String clear1MonthPartition = Clean3NoticeMonitor.clearPartitionMonth(2);
        // 保留1个月 按时间 2025-03-01 00:00:00
        String clear1MonthDate = Clean3NoticeMonitor.clearDate(1);

        // 保留2个月 月分区 p1
        String clear2MonthPartition = Clean3NoticeMonitor.clearPartitionMonth(3);
        // 保留2个月 按时间 2025-02-01 00:00:00
        String clear2MonthDate = Clean3NoticeMonitor.clearDate(2);
        // 保留2个月 天分区 p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28,p29,p30,p31
        String clear2MonthDayPartition = Clean3NoticeMonitor.clearPartitionDay(3);

        // 保留6个月 月分区 p9
        String clear6MonthPartition = Clean3NoticeMonitor.clearPartitionMonth(7);
        // 保留6个月 天分区
        String clear6MonthDayPartition = Clean3NoticeMonitor.clearPartitionDay(7);

        // 对行进行裂变
        List<String> fissileLines = Lists.newArrayList();
        for (String line : sourceLines) {
            // 非日期类型的需要裂变
            if (StringUtils.contains(line, "${clear1MonthDayPartition}")) {
                String[] partitions = clear1MonthDayPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear1MonthDayPartition\\}", partition));
                }
            } else if (StringUtils.contains(line, "${clear1MonthPartition}")) {
                String[] partitions = clear1MonthPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear1MonthPartition\\}", partition));
                }
            } else if (StringUtils.contains(line, "${clear2MonthPartition}")) {
                String[] partitions = clear2MonthPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear2MonthPartition\\}", partition));
                }
            } else if (StringUtils.contains(line, "${clear2MonthDayPartition}")) {
                String[] partitions = clear2MonthDayPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear2MonthDayPartition\\}", partition));
                }
            } else if (StringUtils.contains(line, "${clear6MonthPartition}")) {
                String[] partitions = clear6MonthPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear6MonthPartition\\}", partition));
                }
            } else if (StringUtils.contains(line, "${clear6MonthDayPartition}")) {
                String[] partitions = clear6MonthDayPartition.split(",");
                for (String partition : partitions) {
                    fissileLines.add(line.replaceAll("\\$\\{clear6MonthDayPartition\\}", partition));
                }
            } else {
                // 时间类型不裂变
                fissileLines.add(line.replaceAll("\\$\\{clear1MonthDate\\}", clear1MonthDate).replaceAll("\\$\\{clear2MonthDate\\}", clear2MonthDate));
            }
        }
        return fissileLines;
    }

    ExecuteParam getParam();

    default void clean() {
        // 并发校验
        String locker = RedisCacheHelper.get(LOCK_KEY);
        if (StringUtils.isNotBlank(locker)) {
            throw new RuntimeException("有任务正在执行中: " + locker);
        }

        // 读取请求体
        ExecuteParam executeParam = this.getParam();
        if (Objects.isNull(executeParam) || StringUtils.isBlank(executeParam.getFileKey())) {
            return;
        }

        RedisCacheHelper.put(LOCK_KEY, JsonHelper.toJSONString(executeParam));

        // 异步防止阻塞
        BaseConfig config = new BaseConfig(AbstractMonitor.mainConfig, AbstractMonitor.mainConfig.getPlatform(PlatformEnum.SQL));

        CompletableFuture.runAsync(() -> new DefaultRunner().start(config, executeParam));
    }

}
